// file:include/os/account.h
// autor:jiangxinpeng
// time:2021.3.3
// copyright:(C) by jiangxinpeng,All right are reserved.

#ifndef OS_ACCOUNT_h
#define OS_ACCOUNT_H

#include <lib/type.h>
#include <os/spinlock.h>
#include <os/mutexlock.h>
#include <os/path.h>

// account name and password len
#define ACCOUNT_NAME_LEN 32+1
#define ACCOUNT_NAME_MIN_LEN 6+1
#define ACCOUNT_PASSWORD_LEN 32+1
#define ACCOUNT_PASSWORD_MIN_LEN 8
#define ACCOUNT_ATTRSTR_LEN 8

#define ACCOUNT_CONFIG_BUFF_SIZE (ACCOUNT_NAME_LEN + ACCOUNT_PASSWORD_LEN + ACCOUNT_ATTRSTR_LEN+1)

// account system file name
#define ACCOUNT_FILE_NAME "accout"
#define PERMISSION_FILE_NAME "permission"

#define ROOT_ACCOUNT_NAME "admin"
#define ROOT_ACCOUNT_PASSWORD "admin"

// max account number
#define ACCOUNT_NUM_MAX 10

// account buffer max size
#define ACCOUNT_ATTR_BUFF_MAX (ACCOUNT_ATTRSTR_LEN+1)
#define ACCOUNT_NAME_BUFF_MAX ACCOUNT_NAME_LEN
#define ACCOUNT_PASSWORD_BUFF_MAX ACCOUNT_PASSWORD_LEN

// account valid
// acount name only is dight,char and '_'
#define ACCOUNT_NAME_VALID(name) (((name) >= '0' && (name) <= '9') || ((name) >= 'a' && (name) <= 'z') || ((name) >= 'A' && (name) <= 'Z') || ((name) == '_'))
#define ACCOUNT_PASSWORD_VALID(password) (((password) >= '0' && (password) <= '9') || ((password) >= 'a' && (password) <= 'z') || ((password) >= 'A' && (password) <= 'Z') || ((password) == '_') || ((password) == '~') || ((password) == '!') || ((password) == '@') || ((password) == '#') || ((password) == '$') || ((password) == '%') || ((password) == '^') || ((password) == '&') || ((password) == '&') || ((password) == '*'))

// account level
#define ACCOUNT_LEVEL_ROOT 0
#define ACCOUNT_LEVEL_USER 1
#define ACCOUNT_LEVEL_GUEST 2
#define ACCOUNT_LEVEL_MASK 0xff

// acount status
#define ACCOUNT_STU_LOGINED (1 << 8)
#define ACCOUNT_STU_DISABLE (1 << 9)
#define ACCOUNT_STU_ENABLE (1 << 10)
#define ACCOUNT_STU_LOGOUT (1 << 11)

// account table alloc flags
#define ACCOUNT_FLAG_USING (1 << 31)

// permission database len
#define PERMISS_DATABASE_LEN 32
// permission string len
#define PERMISS_STRING_LEN 32+1
// permission data max
#define PERMISS_DATA_MAX 64

// permission type
#define PERMISS_ATTR_DEVICE 0x01
#define PERMISS_ATTR_FILE 0x02
#define PERMISS_ATTR_FIFO 0x04
// permisstion attribute
#define PERMISS_ATTR_READ 0x08
#define PERMISS_ATTR_WRITE 0x10
#define PERMISS_ATTR_RDWR (PERMISS_ATTR_READ | PERMISS_ATTR_WRITE)
#define PERMISS_ATTR_EXEC 0x40
#define PERMISS_ATTR_HOME 0x80

// account block
typedef struct
{
    int8_t uid;
    int8_t gid;

    char name[ACCOUNT_NAME_LEN];
    char password[ACCOUNT_PASSWORD_LEN];
    // 0-7 account level 8-15 account status
    uint32_t flags;
    uint32_t idx_len;
    spinlock_t lock;
    uint32_t data_index[PERMISS_DATABASE_LEN];
    uint8_t status;
} account_t;

// permission data block
typedef struct
{
    uint32_t attr;
    char str[PERMISS_STRING_LEN];
} permiss_data_t;

// permission database block
typedef struct
{
    mutexlock_t lock;
    uint32_t len;
    permiss_data_t data[PERMISS_DATABASE_LEN];
} permiss_database_t;

extern permiss_database_t *permiss_db;
extern account_t *cur_user;

int PermissionDataBaseLoad();
int PermissionDataBaseSync();
permiss_data_t *PermissionDataBaseSelect(char *str);
void PermissionDataToStr(permiss_data_t *data, void *buff);
int PermissionDataBaseDelByData(char *str);
int PermissionDataBaseDel(int pos);
int PermissionDataBaseInsert(uint32_t attr, char *str);
int PerssionDataBaseSearchFree();
void PermissionDataInit(permiss_data_t *data, uint32_t attr, char *str);
void PermissionDataBaseInit();
int PermissionAutoInsert();
permiss_data_t *PermissionDataBaseSelectByIndex(int idx);
void PermissionDataBaseForEach(void (*callback)(void *, void *), void *arg);

void AccountInit(account_t *accout);
int AccountAddIndex(account_t *accout, uint32_t index);
int AccoutDelIndex(account_t *accout, uint32_t index);
account_t *AccountAlloc();
int AccountFree(account_t *account);
int AccountManagerInit();
int AccountRegister(const char *name, char *password, uint32_t flags);
int AccountUnregister(const char *name);
int AccountNameCheck(const char *name);
int AccountPasswordCheck(const char *name);
account_t *AccountFindByName(const char *name);
int AccountSelfPermissionCheck(const char *str, uint32_t attr);
int AccountPermissionCheck(account_t *account, char *str, uint32_t attr);
int AccountSyncData();
int AccountLogin(const char *name, const char *password);
int AccountLogout(const char *name);
int AccountSync();
int AccountChPwd(char *name, char *old_password, char *new_password);
int AccountScanLine(char *line);
static void AccountBuildFileBuff(account_t *account, char *buff);

int SysLogin(const char *name, const char *password);
int SysLogout(const char *name);
int SysAccountVerify(const char *password);
int SysRegister(const char *name, char *password);
int SysUnRegister(const const char *name);
int SysAccountName(const char *buff, size_t len);
int SysAccountChPwd(const char *name, const char *old_password, const char *new_password);
int SysGetUID();
int SysGetGID();

#endif